﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using VCDIFF;
using VCDIFF.Rebuild;
using System.Collections.Generic;

namespace VCDIFF.Tests
{
    
    
    /// <summary>
    ///This is a test class for RebuildWindowsTest and is intended
    ///to contain all RebuildWindowsTest Unit Tests
    ///</summary>
    [TestClass()]
    public class RebuildWindowsTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for RebuildWindow
        ///</summary>
        [TestMethod()]
        public void RebuildWindowTest()
        {
            RebuildWindows target = new RebuildWindows();
            byte[] windowData = new byte[48];
            windowData[0] = 0x01;
            windowData[1] = 0x8B;
            windowData[2] = 0x2E;
            windowData[3] = 0x00;
            windowData[4] = 0x10;
            windowData[5] = 0x96;
            windowData[6] = 0x5D;
            windowData[7] = 0x00;
            windowData[8] = 0x01;
            windowData[9] = 0x07;
            windowData[10] = 0x02;
            windowData[11] = 0x0A;
            windowData[12] = 0x73;
            windowData[13] = 0x8B;
            windowData[14] = 0x2E;
            windowData[15] = 0x02;
            windowData[16] = 0x73;
            windowData[17] = 0x8B;
            windowData[18] = 0x2E;
            windowData[19] = 0x00;
            windowData[20] = 0x00;

            Window expected = new Window();
            expected.WinIndicator = 0x01;
            expected.SourceSegmentSize = 1454;
            expected.SourceSegmentPosition = 0;
            expected.DeltaEncodingLength = 16;
            expected.TargetWindowSize = 2909;
            expected.DeltaIndicator = 0x00;
            expected.AddAndRunDataLength = 1;
            expected.InstructionsAndSizesLength = 7;
            expected.CopyAddressesLength = 2;
            expected.AddAndRunDataSection = new byte[1] { 0x0A };
            expected.InstructionsAndSizesSection = new byte[7] { 0x73, 0x8B, 0x2E, 0x02, 0x73, 0x8B, 0x2E };
            expected.CopyAddressesSection = new byte[2] { 0x00, 0x00 };

            Window actual = target.RebuildWindow(windowData);
            bool same = true;

            if (expected.WinIndicator != actual.WinIndicator)
                same = false;
            if (expected.SourceSegmentSize != actual.SourceSegmentSize)
                same = false;
            if (expected.SourceSegmentPosition != actual.SourceSegmentPosition)
                same = false;
            if (expected.DeltaEncodingLength != actual.DeltaEncodingLength)
                same = false;
            if (expected.TargetWindowSize != actual.TargetWindowSize)
                same = false;
            if (expected.DeltaIndicator != actual.DeltaIndicator)
                same = false;
            if (expected.AddAndRunDataLength != actual.AddAndRunDataLength)
                same = false;
            if (expected.InstructionsAndSizesLength != actual.InstructionsAndSizesLength)
                same = false;
            if (expected.CopyAddressesLength != actual.CopyAddressesLength)
                same = false;
            if (expected.AddAndRunDataSection.Length != actual.AddAndRunDataSection.Length)
                same = false;
            else
                for (int i = 0; i < expected.AddAndRunDataSection.Length; i++)
                    if (expected.AddAndRunDataSection[i] != actual.AddAndRunDataSection[i])
                        same = false;
            if (expected.InstructionsAndSizesSection.Length != actual.InstructionsAndSizesSection.Length)
                same = false;
            else
                for (int i = 0; i < expected.InstructionsAndSizesSection.Length; i++)
                    if (expected.InstructionsAndSizesSection[i] != actual.InstructionsAndSizesSection[i])
                        same = false;
            if (expected.CopyAddressesSection.Length != actual.CopyAddressesSection.Length)
                same = false;
            else
                for (int i = 0; i < expected.CopyAddressesSection.Length; i++)
                    if (expected.CopyAddressesSection[i] != actual.CopyAddressesSection[i])
                        same = false;

            Assert.AreEqual(true, same);
        }

        /// <summary>
        ///A test for Rebuild
        ///</summary>
        [TestMethod()]
        public void RebuildTest()
        {
            RebuildWindows target = new RebuildWindows();
            byte[] data = new byte[90];
            data[0] = 0xD6;
            data[1] = 0xC3;
            data[2] = 0xC4;
            data[3] = 0x01;
            data[4] = 0x02;
            data[5] = 0x03;
            data[6] = 0x04;
            data[7] = 0x05;
            data[8] = 0x06;

            data[9] = 0x01;
            data[10] = 0x8B;
            data[11] = 0x2E;
            data[12] = 0x00;
            data[13] = 0x10;
            data[14] = 0x96;
            data[15] = 0x5D;
            data[16] = 0x00;
            data[17] = 0x01;
            data[18] = 0x07;
            data[19] = 0x02;
            data[20] = 0x0A;
            data[21] = 0x73;
            data[22] = 0x8B;
            data[23] = 0x2E;
            data[24] = 0x02;
            data[25] = 0x73;
            data[26] = 0x8B;
            data[27] = 0x2E;
            data[28] = 0x00;
            data[29] = 0x00;

            data[30] = 0x02;
            data[31] = 0x8B;
            data[32] = 0x2E;
            data[33] = 0x00;
            data[34] = 0x16;
            data[35] = 0xA2;
            data[36] = 0x0C;
            data[37] = 0x00;
            data[38] = 0x02;
            data[39] = 0x0B;
            data[40] = 0x03;
            data[41] = 0x0A;
            data[42] = 0x0A;
            data[43] = 0x73;
            data[44] = 0x8B;
            data[45] = 0x2E;
            data[46] = 0x02;
            data[47] = 0x73;
            data[48] = 0x8B;
            data[49] = 0x2E;
            data[50] = 0x02;
            data[51] = 0x73;
            data[52] = 0x8B;
            data[53] = 0x2E;
            data[54] = 0x00;
            data[55] = 0x00;
            data[56] = 0x00;

            data[57] = 0x03;
            data[58] = 0x8B;
            data[59] = 0x2E;
            data[60] = 0x00;
            data[61] = 0x1C;
            data[62] = 0x96;
            data[63] = 0x64;
            data[64] = 0x00;
            data[65] = 0x07;
            data[66] = 0x0B;
            data[67] = 0x04;
            data[68] = 0x0A;
            data[69] = 0x62;
            data[70] = 0x6C;
            data[71] = 0x61;
            data[72] = 0x62;
            data[73] = 0x6C;
            data[74] = 0x61;
            data[75] = 0x73;
            data[76] = 0x8B;
            data[77] = 0x2E;
            data[78] = 0x02;
            data[79] = 0x73;
            data[80] = 0x83;
            data[81] = 0x79;
            data[82] = 0x07;
            data[83] = 0x13;
            data[84] = 0x87;
            data[85] = 0x36;
            data[86] = 0x00;
            data[87] = 0x00;
            data[88] = 0x83;
            data[89] = 0x78;

            Window expectedW1 = new Window();
            expectedW1.WinIndicator = 0x01;
            expectedW1.SourceSegmentSize = 1454;
            expectedW1.SourceSegmentPosition = 0;
            expectedW1.DeltaEncodingLength = 16;
            expectedW1.TargetWindowSize = 2909;
            expectedW1.DeltaIndicator = 0x00;
            expectedW1.AddAndRunDataLength = 1;
            expectedW1.InstructionsAndSizesLength = 7;
            expectedW1.CopyAddressesLength = 2;
            expectedW1.AddAndRunDataSection = new byte[1] { 0x0A };
            expectedW1.InstructionsAndSizesSection = new byte[7] { 0x73, 0x8B, 0x2E, 0x02, 0x73, 0x8B, 0x2E };
            expectedW1.CopyAddressesSection = new byte[2] { 0x00, 0x00 };

            Window expectedW2 = new Window();
            expectedW2.WinIndicator = 0x02;
            expectedW2.SourceSegmentSize = 1454;
            expectedW2.SourceSegmentPosition = 0;
            expectedW2.DeltaEncodingLength = 22;
            expectedW2.TargetWindowSize = 4364;
            expectedW2.DeltaIndicator = 0x00;
            expectedW2.AddAndRunDataLength = 2;
            expectedW2.InstructionsAndSizesLength = 11;
            expectedW2.CopyAddressesLength = 3;
            expectedW2.AddAndRunDataSection = new byte[2] { 0x0A, 0x0A };
            expectedW2.InstructionsAndSizesSection = new byte[11] { 0x73, 0x8B, 0x2E, 0x02, 0x73, 0x8B, 0x2E, 0x02, 0x73, 0x8B, 0x2E };
            expectedW2.CopyAddressesSection = new byte[3] { 0x00, 0x00, 0x00 };

            Window expectedW3 = new Window();
            expectedW3.WinIndicator = 0x03;
            expectedW3.SourceSegmentSize = 1454;
            expectedW3.SourceSegmentPosition = 0;
            expectedW3.DeltaEncodingLength = 28;
            expectedW3.TargetWindowSize = 2916;
            expectedW3.DeltaIndicator = 0x00;
            expectedW3.AddAndRunDataLength = 7;
            expectedW3.InstructionsAndSizesLength = 11;
            expectedW3.CopyAddressesLength = 4;
            expectedW3.AddAndRunDataSection = new byte[7] { 0x0A, 0x62, 0x6C, 0x61, 0x62, 0x6C, 0x61 };
            expectedW3.InstructionsAndSizesSection = new byte[11] { 0x73, 0x8B, 0x2E, 0x02, 0x73, 0x83, 0x79, 0x07, 0x13, 0x87, 0x36 };
            expectedW3.CopyAddressesSection = new byte[4] { 0x00, 0x00, 0x83, 0x78 };

            IList<Window> expectedList = new List<Window>();
            expectedList.Add(expectedW1);
            expectedList.Add(expectedW2);
            expectedList.Add(expectedW3);

            IList<Window> actual = target.Rebuild(data);
            bool same = true;
            int index = 0;

            foreach (Window window in expectedList)
            {
                if (window.WinIndicator != actual[index].WinIndicator)
                    same = false;
                if (window.SourceSegmentSize != actual[index].SourceSegmentSize)
                    same = false;
                if (window.SourceSegmentPosition != actual[index].SourceSegmentPosition)
                    same = false;
                if (window.DeltaEncodingLength != actual[index].DeltaEncodingLength)
                    same = false;
                if (window.TargetWindowSize != actual[index].TargetWindowSize)
                    same = false;
                if (window.DeltaIndicator != actual[index].DeltaIndicator)
                    same = false;
                if (window.AddAndRunDataLength != actual[index].AddAndRunDataLength)
                    same = false;
                if (window.InstructionsAndSizesLength != actual[index].InstructionsAndSizesLength)
                    same = false;
                if (window.CopyAddressesLength != actual[index].CopyAddressesLength)
                    same = false;
                if (window.AddAndRunDataSection.Length != actual[index].AddAndRunDataSection.Length)
                    same = false;
                else
                    for (int i = 0; i < window.AddAndRunDataSection.Length; i++)
                        if (window.AddAndRunDataSection[i] != actual[index].AddAndRunDataSection[i])
                            same = false;
                if (window.InstructionsAndSizesSection.Length != actual[index].InstructionsAndSizesSection.Length)
                    same = false;
                else
                    for (int i = 0; i < window.InstructionsAndSizesSection.Length; i++)
                        if (window.InstructionsAndSizesSection[i] != actual[index].InstructionsAndSizesSection[i])
                            same = false;
                if (window.CopyAddressesSection.Length != actual[index].CopyAddressesSection.Length)
                    same = false;
                else
                    for (int i = 0; i < window.CopyAddressesSection.Length; i++)
                        if (window.CopyAddressesSection[i] != actual[index].CopyAddressesSection[i])
                            same = false;
                index++;
            }

            Assert.AreEqual(true, same);
        }

        /// <summary>
        ///A test for GetWindowSize
        ///</summary>
        [TestMethod()]
        public void GetWindowSizeTest()
        {
            RebuildWindows target = new RebuildWindows();
            byte[] data = new byte[21];
            data[0] = 0x01;
            data[1] = 0x8B;
            data[2] = 0x2E;
            data[3] = 0x00;
            data[4] = 0x10;
            data[5] = 0x96;
            data[6] = 0x5D;
            data[7] = 0x00;
            data[8] = 0x01;
            data[9] = 0x07;
            data[10] = 0x02;
            data[11] = 0x0A;
            data[12] = 0x73;
            data[13] = 0x8B;
            data[14] = 0x2E;
            data[15] = 0x02;
            data[16] = 0x73;
            data[17] = 0x8B;
            data[18] = 0x2E;
            data[19] = 0x00;
            data[20] = 0x00;
            ulong expected = 21;
            ulong actual = target.GetWindowSize(data);
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for GetWindowHeaderSize
        ///</summary>
        [TestMethod()]
        public void GetWindowHeaderSizeTest()
        {
            RebuildWindows target = new RebuildWindows();
            byte[] data = new byte[21];
            data[0] = 0x01;
            data[1] = 0x8B;
            data[2] = 0x2E;
            data[3] = 0x00;
            data[4] = 0x10;
            data[5] = 0x96;
            data[6] = 0x5D;
            data[7] = 0x00;
            data[8] = 0x01;
            data[9] = 0x07;
            data[10] = 0x02;
            data[11] = 0x0A;
            data[12] = 0x73;
            data[13] = 0x8B;
            data[14] = 0x2E;
            data[15] = 0x02;
            data[16] = 0x73;
            data[17] = 0x8B;
            data[18] = 0x2E;
            data[19] = 0x00;
            data[20] = 0x00;
            ulong expected = 4;
            ulong actual = target.GetWindowHeaderSize(data);

            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for GetWindowData
        ///</summary>
        [TestMethod()]
        public void GetWindowDataTest()
        {
            RebuildWindows target = new RebuildWindows();
            byte[] data = new byte[48];
            data[0] = 0x01;
            data[1] = 0x8B;
            data[2] = 0x2E;
            data[3] = 0x00;
            data[4] = 0x10;
            data[5] = 0x96;
            data[6] = 0x5D;
            data[7] = 0x00;
            data[8] = 0x01;
            data[9] = 0x07;
            data[10] = 0x02;
            data[11] = 0x0A;
            data[12] = 0x73;
            data[13] = 0x8B;
            data[14] = 0x2E;
            data[15] = 0x02;
            data[16] = 0x73;
            data[17] = 0x8B;
            data[18] = 0x2E;
            data[19] = 0x00;
            data[20] = 0x00;

            data[21] = 0x02;
            data[22] = 0x8B;
            data[23] = 0x2E;
            data[24] = 0x00;
            data[25] = 0x16;
            data[26] = 0xA2;
            data[27] = 0x0C;
            data[28] = 0x00;
            data[29] = 0x02;
            data[30] = 0x0B;
            data[31] = 0x03;
            data[32] = 0x0A;
            data[33] = 0x0A;
            data[34] = 0x73;
            data[35] = 0x8B;
            data[36] = 0x2E;
            data[37] = 0x02;
            data[38] = 0x73;
            data[39] = 0x8B;
            data[40] = 0x2E;
            data[41] = 0x02;
            data[42] = 0x73;
            data[43] = 0x8B;
            data[44] = 0x2E;
            data[45] = 0x00;
            data[46] = 0x00;
            data[47] = 0x00;

            byte[] expected = new byte[21];
            expected[0] = 0x01;
            expected[1] = 0x8B;
            expected[2] = 0x2E;
            expected[3] = 0x00;
            expected[4] = 0x10;
            expected[5] = 0x96;
            expected[6] = 0x5D;
            expected[7] = 0x00;
            expected[8] = 0x01;
            expected[9] = 0x07;
            expected[10] = 0x02;
            expected[11] = 0x0A;
            expected[12] = 0x73;
            expected[13] = 0x8B;
            expected[14] = 0x2E;
            expected[15] = 0x02;
            expected[16] = 0x73;
            expected[17] = 0x8B;
            expected[18] = 0x2E;
            expected[19] = 0x00;
            expected[20] = 0x00;

            byte[] actual = target.GetWindowData(data);
            bool same = true;

            if (expected.Length != actual.Length)
                same = false;
            else
                for (int i = 0; i < expected.Length; i++)
                    if (expected[i] != actual[i])
                        same = false;

            Assert.AreEqual(true, same);
        }

        /// <summary>
        ///A test for RebuildWindows Constructor
        ///</summary>
        [TestMethod()]
        public void RebuildWindowsConstructorTest()
        {
            RebuildWindows target = new RebuildWindows();
        }
    }
}
